﻿using System.Collections.Generic;
using System.Collections;
using System;

namespace Domain
{
    public class HuffmanCoding
    {
            public HuffmanTree Tree = new HuffmanTree();
            public string Line = "";

            public bool OneSymbolInString( string str)
            {
                if (str.Length == 1) return true;
                for (int i = 0; i < str.Length-1; i++)
                {
                    if (str[i] != str[i + 1]) return false;
                }
                return true;
            }

            public void BuildTree(string input)
            {
                Tree.Build(input);
                Line = input;
            }

            public BitArray Encode(string input)
            {
                List<bool> encodedLine = new List<bool>();
                if (OneSymbolInString(input) && (OneSymbolInString(Line)))
                {
                    if(Tree.Root.GetSymbolCode(input[0], new List<bool>()) == null) return null;
                    for (int j = 0; j < input.Length; j++)
                       encodedLine.Add(false);
                }
                else
                    for (int i = 0; i < input.Length; i++)
                    {
                        List<bool> encodedSymbol = Tree.Root.GetSymbolCode(input[i], new List<bool>());
                       
                        if (encodedSymbol != null)
                        {
                                encodedLine.AddRange(encodedSymbol);
                        }
                        else return null;
                    }
                BitArray bits = new BitArray(encodedLine.ToArray());
                return bits;
            }

            public string Decode(BitArray bits)
            {
                HuffmanTreeNode CurrentSubTree = Tree.Root;
                string DecodedString = "";
                int i = 0;

                foreach (bool bit in bits)
                {
                    i++;
                    if (bit)
                    {
                        if (CurrentSubTree.Right != null)
                        {
                            CurrentSubTree = CurrentSubTree.Right;
                        }
                        else return null;
                    }
                    else
                    {
                        if (CurrentSubTree.Left != null)
                        {
                            CurrentSubTree = CurrentSubTree.Left;
                        }
                        else return null;
                    }

                    if (CurrentSubTree.IsLeaf())
                    {
                        DecodedString += CurrentSubTree.Symbol;
                        CurrentSubTree = Tree.Root;
                    }
                    else if (i == bits.Length) return null;
                }

                return DecodedString;
            }

            public Dictionary<char, BitArray> CodeOfAlphabet()
            {
                if (OneSymbolInString(Line))
                {
                    var DicResult = new Dictionary<char, BitArray>();
                    DicResult.Add(Line[0], new BitArray(new bool[]{false}));
                    return DicResult;
                }
                return Tree.GetCodeOfAlphabet();
            }
    }
}
